#ifndef _SIM_AXI_H
#define _SIM_AXI_H

#include <stdint.h>
#include <queue>

#include "ram.h"
#include "commonprint.h"
#include "vcstop.h"

#define SIM_AXI_WIDTH 4
#define SIM_AXI_ID    7
#define SIM_AXI_USER  4

namespace AXISim{
struct AXI_rreq{
  uint64_t  addr     ; // 64
  uint32_t  size     ; 
  uint32_t  burst    ;
  uint32_t  prot     ; // 8
  uint32_t  cache    ;
  uint32_t  id       ; // 8
  uint32_t  len      ; // 8
  uint32_t  qos      ;
  uint32_t  region   ; // 8
  uint32_t  lock     ;
  uint32_t  user     ;
};

struct AXI_wreq{
  uint64_t  addr     ; // 64
  uint32_t  size     ; 
  uint32_t  burst    ;
  uint32_t  prot     ; // 8
  uint32_t  cache    ; 
  uint32_t  id       ; // 8
  uint32_t  len      ; // 8
  uint32_t  qos      ;
  uint32_t  region   ; // 8
  uint32_t  lock     ;
  uint32_t  user     ;
};

struct AXI_rtask{
  uint64_t  addr     ; // 64
  uint32_t  size     ; 
  uint32_t  burst    ;
  uint32_t  len      ;
  uint32_t  cache    ;
  bool      read     ;
  uint64_t  bound    ;
};

struct AXI_wtask{
  uint64_t  addr     ; // 64
  uint32_t  size     ; 
  uint32_t  burst    ;
  uint32_t  len      ;
  uint32_t  id       ;
  uint32_t  cache    ;
  uint64_t  bound    ;
};

class AXI_wrapper {
private:
    class VCSTop * master;
    class RAM *ram;

    std::queue<struct AXI_rreq> rreq_list;
    std::queue<struct AXI_wreq> wreq_list;
    bool winflight;
    bool wfinish;
    bool rinflight;

    struct AXI_rtask rtask;
    struct AXI_wtask wtask;
    struct AXI_wtask wtask_finished;

public:
    AXI_wrapper(VCSTop *master, class RAM *ram);
    ~AXI_wrapper();

    int save_signal(int cylces);
    int handle_aw(int cycles);
    int handle_w(int cycles);
    int handle_ar(int cycles);
    int handle_r(int cycles);
    int handle_b(int cycles);

    uint64_t addr_inc(bool wrap,uint64_t bound,uint64_t offset, uint64_t addr);
    void  get_rtask(int cycles);
    void  get_wtask(int cycles);
    void  update_rtask(int cycles);
    void  update_wtask(int cycles);
    bool hasinit = false;
};

}
#endif